/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.quangtin3.reverse;

import com.quangtin3.Bouncing;
import com.quangtin3.Utils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;
import org.apache.log4j.Logger;

/**
 * Side A of reversal relay.
 * @author quangtin3@gmai.com
 */
public class SideA implements Runnable {

    private int transPort = 3105,  bncPort = 8583;
    private ServerSocket serverSockA,  serverSockBnc;
    static String REQUEST_CONNECT = "connect to 127.0.0.1:8585";
    static String RESPONSE_CONNECT_OK = "connect to 127.0.0.1:8585 ok";
    static String RESPONSE_CONNECT_FAIL = "connect to 127.0.0.1:8585 fail";
    private Logger log;

    public static void main(String[] args) {
        new SideA(Logger.getLogger("sideA"));
    }

    public SideA(Logger log) {
        this.log = log;
        Thread t = new Thread(this, "SideA");
        t.start();
    }

    public void run() {
        log.info("system start");

        int i_trans = 0;
        try {

            serverSockA = new ServerSocket(transPort);
            log.info("ReverseRelay listening on port " + transPort);

            serverSockBnc = new ServerSocket(bncPort);
            log.info("Bouncing listening on port " + bncPort);

            while (true) {
                i_trans++;

                //accept                
                Socket sock_a = serverSockA.accept();
                Writer out = new OutputStreamWriter(sock_a.getOutputStream(), "8859_1");
                BufferedReader in = new BufferedReader(
                        new InputStreamReader(sock_a.getInputStream(), "8859_1"));

                log.info("Trans accept connection " + i_trans + " from " + sock_a.getInetAddress().getHostAddress());

                boolean oneMoreBncSuccess = false;
                int i_bnc_count = 0;

                while (!oneMoreBncSuccess) {
                    i_bnc_count++;
                    Socket sock_bnc = serverSockBnc.accept();
                    log.info("Bounc request " + i_bnc_count + " from " + sock_bnc.getInetAddress().getHostAddress());

                    //send connect request 
                    out.write(REQUEST_CONNECT);
                    out.flush();
                    log.info("send " + REQUEST_CONNECT);

                    //receive connect request response
                    char[] cbuff = new char[256];
                    int len = in.read(cbuff);
                    String result = Utils.getString(cbuff, len);
                    log.info("receive " + result);

                    if (result.equalsIgnoreCase(RESPONSE_CONNECT_OK)) {
                        //if (true) {
                        //Bouncing it
                        new Bouncing(sock_bnc, sock_a, log);
                        new Bouncing(sock_a, sock_bnc, log);
                        log.info("one more boucing...");
                        oneMoreBncSuccess = true;
                    } else {
                        log.info("fail, so close connect");
                        sock_bnc.close();
                        log.info("colse sock_bnc");
                        oneMoreBncSuccess = false;
                    }
                }
            }
        } catch (Exception e) {
            log.info("error " + e.getMessage());
        } finally {
            try {
                serverSockA.close();
                serverSockBnc.close();
            } catch (IOException e) {
            }

            log.info("system stop.");
        }
    }
}
